package physicsNatures;

import java.awt.Point;
import core.physics.WorldForceManager;
import com.golden.gamedev.object.Sprite;
import util.math.Angle;
import util.physics.Force;
import util.physics.Velocity;

/**
 * "Physics nature" for an object which follows Newtonian mechanics.
 * Extends AbstractPhysicsNature.
 * 
 * @author Anne Weng
 * @author Nathan Klug
 *
 */
public class NewtonianPhysicsNature extends AbstractPhysicsNature{

    private Angle myAngularVelocity;
    private Point myCenterOfMass;
    private double myCoefficientOfFriction;

    public NewtonianPhysicsNature(Sprite sprite, double mass) {
        super(sprite, mass);
        //TODO: set other defaults
    }

    /**
     * Applies a force to the object which will change its velocity.
     */
    @Override
    public void applyForce(Force force, long elapsedTime) {
        Velocity deltaVelocity = new Velocity(force.getMagnitude() * elapsedTime / getMass(), force.getAngle());
        Velocity spriteVelocity = getVelocity();
        spriteVelocity.addVector(deltaVelocity);
        setVelocity(spriteVelocity);
    }

    /**
     * Updates the object using physics and then updates the velocities.
     * !!!!!Should we update velocities and then update the object?
     */
    @Override
    public void updateWithPhysics(long elapsedTime) {
        // TODO: Fix for Golden T's weird angles
        mySprite.move(getVelocity().getXComponent() * elapsedTime, getVelocity().getYComponent() * elapsedTime);
        // TODO: ROTATE via angular velocity
        
        // TODO: Friction?
        WorldForceManager.getInstance().applyWorldForces(this, elapsedTime);
    }
    
    /**
     * Method for telling the object to calculate and set its velocity after a collision.
     * Uses the derivation of the Law of Conservation of Momentum using the coefficient of
     * restitution to calculate.
     * Source: http://en.wikipedia.org/wiki/Coefficient_of_restitution
     */
    @SuppressWarnings("unused")
    @Override
    public void collisionOccurred(AbstractPhysicsNature otherObject, Angle angleOfImpact, Point pointOfCollision, double coefficientOfRestitution) {
        Velocity oldVelocity1 = getVelocity();
        Velocity oldVelocity2 = otherObject.getVelocity();
        double myParallel = getVelocity().getParallelComponent(angleOfImpact);
        double myPerp = getVelocity().getPerpComponent(angleOfImpact);
        double otherParallel = otherObject.getVelocity().getParallelComponent(angleOfImpact);
        double otherPerp = otherObject.getVelocity().getPerpComponent(angleOfImpact);
        
        double parallelNumerator = getMass()*myParallel + otherObject.getMass()*otherParallel
                        + otherObject.getMass()*coefficientOfRestitution*(otherParallel-myParallel);
        double perpNumerator = getMass()*myPerp + otherObject.getMass()*otherPerp
                        + otherObject.getMass()*coefficientOfRestitution*(otherPerp-myPerp);
        double denominator = getMass() + otherObject.getMass();
        
        Velocity newVelocity = new Velocity(perpNumerator/denominator, parallelNumerator/denominator, angleOfImpact); 
        setVelocity(newVelocity);
    }


}
